package com.sxhuayuan.parking.aspects;

import java.lang.reflect.Field;

import javax.annotation.Resource;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;

import com.sxhuayuan.parking.annotation.GetFromRedis;
import com.sxhuayuan.parking.annotation.SetToRedis;
import com.sxhuayuan.parking.exception.MyException;
import com.sxhuayuan.parking.service.RedisService;

/**
 * redis缓存
 * 
 * @author DELL
 *
 */
//@Component("redisCacheAspect")
//@Aspect
@Deprecated
public class RedisCacheAspect {

	Logger log = LoggerFactory.getLogger(getClass());

	@Resource(name = "redisServiceImpl")
	RedisService redisService;

	// 自动保存
	@Pointcut("@annotation(com.sxhuayuan.parking.annotation.SetToRedis)")
	public void setToRedisCutPoint() {
	}

	// 自动读取
	@Pointcut("@annotation(com.sxhuayuan.parking.annotation.GetFromRedis)")
	public void getFromRedisCutPoint() {
	}

	@Before("setToRedisCutPoint() && @annotation(setToRedis)")
	public void beforeSetToRedis(JoinPoint joinPoint, SetToRedis setToRedis) {
		log.debug("after setToRedis");
		// 实体类自身
		Object bean = joinPoint.getThis();
		// set的参数
		Object value = joinPoint.getArgs()[0];
		String uniqueFieldName = setToRedis.uniqueField();
		Object uniqueValue = getFieldValue(bean, uniqueFieldName);
		String keyPrefix = bean.getClass().getName();
		String key = String.format("%s.%s.%s", keyPrefix, setToRedis.value(), uniqueValue.toString());
		boolean update = redisService.updateString(key, value.toString());
		if (!update) {
			log.warn("redis 缓存字段失败: " + setToRedis.value());
		}
	}

	@Before("getFromRedisCutPoint() && @annotation(getFromRedis)")
	public void afterGetFromRedis(JoinPoint joinPoint, GetFromRedis getFromRedis) {
		log.debug("after redisCacheRead");
		String fieldName = getFromRedis.value();
		Object bean = joinPoint.getThis();
		String uniqueFieldName = getFromRedis.uniqueField();
		Object uniqueValue = getFieldValue(bean, uniqueFieldName);
		String keyPrefix = bean.getClass().getName();
		String key = String.format("%s.%s.%s", keyPrefix, fieldName, uniqueValue.toString());
		String string = redisService.getString(key);
		if (string == null) {
			log.warn("读取 redis 缓存字段失败: " + fieldName);
		}
		ReflectionUtils.setField(getField(bean, getFromRedis.value()), bean, string);
	}

	// 解析动态值
	@SuppressWarnings("unused")
	private Object evalExpression(String expression, JoinPoint joinPoint) {
		// 动态解析
		String[] split = expression.split(".");
		MethodSignature ms = (MethodSignature) joinPoint.getSignature();
		Object[] args = joinPoint.getArgs();
		String[] parameterNames = ms.getParameterNames();
		Object prev = null;
		for (int i = 0; i < parameterNames.length; i++) {
			String p = parameterNames[i];
			if (p.equals(split[0])) {
				prev = args[i];
			}
		}
		if (prev == null)
			throw new MyException(expression + " returns null!");
		if (split.length > 1) {
			for (int i = 1; i < split.length; i++) {
				prev = getFieldValue(prev, split[i]);
				if (prev == null)
					throw new MyException(expression + " returns null!");
			}
		}
		return prev;
	}

	private Field getField(Object obj, String fieldName) {
		Field field = ReflectionUtils.findField(obj.getClass(), fieldName);
		return field;
	}

	private Object getFieldValue(Object obj, String fieldName) {
		Field field = getField(obj, fieldName);
		Object value = null;
		if (field != null) {
			field.setAccessible(true);
			try {
				value = field.get(obj);
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
		return value;
	}
}
